<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta http-equiv="Content-Language" content="zh-CN"><title>systemd.generator
  中文手册 [金步国]</title><style>
@font-face { font-family: "JinBuGuoWebMono"; src: url("http://www.jinbuguo.com/d/mono.ttf") format("truetype"); }
* { font-family: "JinBuGuoWebMono", "Ubuntu Mono", "Consolas", "Menlo", monospace; }
body { margin:10px; }
h1 { text-align:center; background:#ddd; }
h2#auth_name { text-align:center; margin: 10px 5%; }

    a.headerlink {
      color: #c60f0f;
      font-size: 0.8em;
      padding: 0 4px 0 4px;
      text-decoration: none;
      visibility: hidden;
    }

    a.headerlink:hover {
      background-color: #c60f0f;
      color: white;
    }

    h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, dt:hover > a.headerlink {
      visibility: visible;
    }
</style><script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><h1>systemd.generator 中文手册</h1><h2 id="auth_name">译者：<strong><a href="http://www.jinbuguo.com/">金步国</a></strong></h2><hr><h3>版权声明</h3><p>本文译者是一位开源理念的坚定支持者，所以本文虽然不是软件，但是遵照开源的精神发布。</p><ul><li>无担保：本文译者不保证译文内容准确无误，亦不承担任何由于使用此文档所导致的损失。</li><li>自由使用：任何人都可以自由的<u>阅读/链接/打印</u>此文档，无需任何附加条件。</li><li>名誉权：任何人都可以自由的<u>转载/引用/再创作</u>此文档，但必须保留译者署名并注明出处。</li></ul><h3>其他作品</h3><p>本文译者十分愿意与他人分享劳动成果，如果你对我的其他翻译作品或者技术文章有兴趣，可以在如下位置查看现有的作品集：</p><ul><li><a href="http://www.jinbuguo.com/">金步国作品集</a> [ <a href="http://www.jinbuguo.com/">http://www.jinbuguo.com/</a> ]</li></ul><h3>联系方式</h3><p>由于译者水平有限，因此不能保证译文内容准确无误。如果你发现了译文中的错误(哪怕是错别字也好)，请来信指出，任何提高译文质量的建议我都将虚心接纳。</p><ul><li>Email(QQ)：70171448在QQ邮箱</li></ul><hr><a href="systemd.index.html">手册索引</a> ·
  <a href="systemd.directives.html">指令索引</a><span style="float:right">systemd-241</span><hr><div class="refentry"><a name="systemd.generator"></a><div class="titlepage"></div><div class="refnamediv"><h2>名称</h2><p>systemd.generator — systemd 单元生成器</p></div><div class="refsynopsisdiv"><h2>大纲</h2><div class="cmdsynopsis"><p><code class="command">/path/to/generator</code>   <em class="replaceable"><code>normal-dir</code></em>   <em class="replaceable"><code>early-dir</code></em>   <em class="replaceable"><code>late-dir</code></em> </p></div><p>
      </p><div class="literallayout"><p>系统生成器目录<code class="filename">/run/systemd/system-generators/*</code><br>
<code class="filename">/etc/systemd/system-generators/*</code><br>
<code class="filename">/usr/local/lib/systemd/system-generators/*</code><br>
<code class="filename">/usr/lib/systemd/system-generators/*</code></p></div><p>
    </p><p>
      </p><div class="literallayout"><p>用户生成器目录<code class="filename">/run/systemd/user-generators/*</code><br>
<code class="filename">/etc/systemd/user-generators/*</code><br>
<code class="filename">/usr/local/lib/systemd/user-generators/*</code><br>
<code class="filename">/usr/lib/systemd/user-generators/*</code></p></div><p>
    </p></div><div class="refsect1"><a name="id-1.5"></a><h2 id="描述">描述<a class="headerlink" title="Permalink to this headline" href="systemd.generator.html#%E6%8F%8F%E8%BF%B0">¶</a></h2><p>本文所说的"生成器"，
    本质上是位于上文所列目录中的一些可执行程序。
    <a href="systemd.html#"><span class="citerefentry"><span class="refentrytitle">systemd</span>(1)</span></a>
    将会在其自身刚启动的早期、以及重新加载其自身的配置信息时，
    执行这些单元生成器(也就是在加载单元文件之前执行)。
    生成器的主要目的是将非单元配置转化为动态生成的单元文件。</p><p>每个生成器都接受三个目录参数，用作输出目录。
    生成器在这三个目录中动态生成单元文件(常规单元、
    实例单元、模板单元)、
    单元配置片段(位于 <code class="filename">.d/</code> 目录中)、
    指向单元文件的软连接(表示单元间额外的依赖关系、表示单元的别名、表示基于现有模板实例化的单元)。
    因为这些目录包含在
    <a href="systemd.html#"><span class="citerefentry"><span class="refentrytitle">systemd</span>(1)</span></a>
    的单元加载路径中，
    所以生成的配置能够扩展或覆盖现有的定义。</p><p>不同的生成器输出目录拥有不同的优先级，
    由高到低排列，依次为：
    <code class="filename">…/generator.early</code> 、
    <code class="filename">/etc</code> 、
    <code class="filename">…/generator</code> 、
    <code class="filename">/usr</code> 、
    <code class="filename">…/generator.late</code> 。
    详见下文以及
    <a href="systemd.unit.html#"><span class="citerefentry"><span class="refentrytitle">systemd.unit</span>(5)</span></a> 手册。
    </p><p>生成器的加载目录取决于编译时的配置，
    一般情况下(--prefix=/usr)，就是上一小节所列的目录。
    系统单元生成器与用户单元生成器分别从
    <code class="filename">system-generators/</code> 与
    <code class="filename">user-generators/</code> 目录中加载。
    位于列表中较前目录中的生成器，将会覆盖列表中较后目录中的同名生成器，也就是列表中较前的目录的优先级也更高。
    因此，可以使用高优先级目录中的一个指向
    <code class="filename">/dev/null</code> 的同名软连接(或空文件)，
    去屏蔽低优先级目录中的一个同名生成器(也就是禁止它运行)。
    注意，生成器目录的优先级顺序与单元目录的优先级顺序并不相同，
    具体就是
    <code class="filename">/run</code> 目录的优先级比
    <code class="filename">/etc</code> 目录更高。</p><p>在安装或更新了生成器之后，
    必须执行 <span class="command"><strong>systemctl daemon-reload</strong></span> 命令才能最终实际生效。
    该命令将会删除先前的单元生成器所创建的所有单元文件与软连接，
    然后重新运行所有生成器来重新创建单元文件与软连接，最后再让
    <span class="command"><strong>systemd</strong></span> 重新加载所有的单元文件。详见
    <a href="systemctl.html#"><span class="citerefentry"><span class="refentrytitle">systemctl</span>(1)</span></a>
    手册。
    </p></div><div class="refsect1"><a name="id-1.6"></a><h2 id="输出目录">输出目录<a class="headerlink" title="Permalink to this headline" href="systemd.generator.html#%E8%BE%93%E5%87%BA%E7%9B%AE%E5%BD%95">¶</a></h2><p>需要给单元生成器传递三个目录参数，
    以指示所生成的单元文件或软连接的存放位置。
    默认情况下，这些参数是包含在
    <span class="command"><strong>systemd</strong></span> 单元目录中的运行时目录，
    但是出于调试目的，也可以设为其他路径。</p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p><em class="parameter"><code>normal-dir</code></em></p><p>对于系统生成器来说，一般是 <code class="filename">/run/systemd/generator</code>
        目录；对于用户生成器来说，一般是
        <code class="filename">$XDG_RUNTIME_DIR/generator</code> 目录。
        此目录中的单元文件能够覆盖厂商提供的单元文件(<code class="filename">/usr</code>)，
        但是不能覆盖本地系统管理员/普通用户的单元文件(<code class="filename">/etc</code>)。
        </p></li><li class="listitem"><p><em class="parameter"><code>early-dir</code></em></p><p>对于系统生成器来说，一般是 <code class="filename">/run/systemd/generator.early</code>
        目录；对于用户生成器来说，一般是
        <code class="filename">$XDG_RUNTIME_DIR/generator.early</code> 目录。
        此目录中的单元文件能够覆盖
        <code class="filename">/usr</code>, <code class="filename">/run</code>,
        <code class="filename">/etc</code> 中的单元文件。
        也就是说，此目录中的单元文件能够覆盖所有单元文件，
        包括厂商提供的单元文件以及本地系统管理员/普通用户的单元文件。</p></li><li class="listitem"><p><em class="parameter"><code>late-dir</code></em></p><p>对于系统生成器来说，一般是 <code class="filename">/run/systemd/generator.late</code>
        目录；对于用户生成器来说，一般是
        <code class="filename">$XDG_RUNTIME_DIR/generator.late</code> 目录。
        此目录中的单元文件不会覆盖任何现存的单元文件，
        仅用于扩展单元文件。
        任何现存的单元文件的优先级都高于此目录中的单元文件。</p></li></ol></div></div><div class="refsect1"><a name="id-1.7"></a><h2 id="编写单元生成器的注意事项">编写单元生成器的注意事项<a class="headerlink" title="Permalink to this headline" href="systemd.generator.html#%E7%BC%96%E5%86%99%E5%8D%95%E5%85%83%E7%94%9F%E6%88%90%E5%99%A8%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">¶</a></h2><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>所有单元生成器都会在同一时间被并行执行。
        这就要求所有单元生成器之间不能存在依赖关系，
        并且足够小巧以适用这种并发式的运行场景。
        </p></li><li class="listitem"><p>单元生成器在系统启动的早期运行，因此它不能依赖于任何其他单元。
        单元生成器在运行过程中不能与任何其他进程通信，
        包括与日志记录进程
        <a href="http://man7.org/linux/man-pages/man3/syslog.3.html"><span class="citerefentry"><span class="refentrytitle">syslog</span>(3)</span></a>
        或 <span class="command"><strong>systemd</strong></span> 自身都不行，当然，更不要说使用
        <a href="systemctl.html#"><span class="citerefentry"><span class="refentrytitle">systemctl</span>(1)</span></a>
        工具了。此外，例如 <code class="filename">/var</code> 与
        <code class="filename">/home</code> 这样的非关键文件系统也是尚未挂载的。
        单元生成器只能使用最基本的内核功能，
        并且只能假定 <code class="filename">/sys</code>, <code class="filename">/proc</code>,
        <code class="filename">/dev</code>, <code class="filename">/usr</code> 已经被挂载。
        </p></li><li class="listitem"><p>单元生成器生成的单元文件将会在重新加载配置文件时被删除。
        换句话说，就是单元生成器生成的单元的生命周期与
         <span class="command"><strong>systemd</strong></span> 自身的生命周期是紧紧绑定在一起的。</p></li><li class="listitem"><p>单元生成器应该仅仅用于生成单元文件与指向单元文件的软连接，
        而不应该做任何与配置相关的工作。
        由于上文提到的生命周期的原因，单元生成器并不适用于为服务单元动态生成配置文件。
        如果你需要为某个服务单元动态生成配置文件，
        那么你应该使用一个普通的服务单元，
        并强迫命令该单元先于被配置的服务单元启动。</p></li><li class="listitem"><p>由于在系统启动的早期阶段，
        <a href="http://man7.org/linux/man-pages/man3/syslog.3.html"><span class="citerefentry"><span class="refentrytitle">syslog</span>(3)</span></a>

        处于不可用状态(见上文)，必须将日志信息写入到
        <code class="filename">/dev/kmsg</code> 文件中。</p></li><li class="listitem"><p>在动态生成的单元文件中使用 <code class="varname">SourcePath=</code>
        指明其来源于哪个配置文件通常是个好主意。
        这样做可以帮助用户轻松的理解该单元是派生于哪个配置文件，
        同时也有助于让 systemd 及时的发出警告：
        磁盘上的配置文件已经发生变化，
        但是我现在还没有刷新动态单元。</p></li><li class="listitem"><p>单元生成器可能会动态生成单元文件，
        也可能只是通过软连接将已有的单元添加到其他单元的 <code class="filename">.wants/</code> 或
        <code class="filename">.requires/</code> 目录中。
        通常，在实践中，最佳做法是尽量使用单元生成器从 <code class="filename">/usr</code> 中的模版实例化出一个单元，
        而不是从头创建一个完整的动态单元文件。
        当然，这只能用于仅使用单个参数的场合。</p></li><li class="listitem"><p>虽然你实际上可以使用 shell 脚本来实现一个单元生成器，但是我们还是强烈建议你使用C语言来实现。
        因为单元生成器都以同步的方式执行，
        所以执行速度较慢脚本会拖慢系统的启动速度。</p></li><li class="listitem"><p>关于单元文件之间的覆盖，
        我们应该尽量遵守如下两条规则：</p><div class="orderedlist"><ol class="orderedlist" type="i"><li class="listitem"><p>用户配置应该覆盖厂商的配置。
            在大多数情况下，这意味着 <code class="filename">/etc</code> 中的内容应该覆盖
            <code class="filename">/usr</code> 中的内容。</p></li><li class="listitem"><p>原生配置应该覆盖非原生配置。
            在大多数情况下，这意味着
            动态生成的单元文件不应该覆盖系统上已有的单元文件。</p></li></ol></div><p>对于上述两个原则，第一个原则应该被严格遵守，而第二个原则在某些场合有可能会被打破。
        因此，在决定使用
        argv[1], argv[2], argv[3] 之中的哪一个时，一般应该默认使用
        argv[1]</p></li><li class="listitem"><p>与其写一堆单元生成器来兼容传统的配置方式，
        不如直接舍弃这些不符合 systemd 规范的传统配置方式，转而使用 systemd 风格的配置方式。
        就让那些老旧的配置方式消失在历史的垃圾桶中吧！
        </p></li></ul></div></div><div class="refsect1"><a name="id-1.8"></a><h2 id="例子">例子<a class="headerlink" title="Permalink to this headline" href="systemd.generator.html#%E4%BE%8B%E5%AD%90">¶</a></h2><div class="example"><a name="id-1.8.2"></a><p class="title"><b>例 1. systemd-fstab-generator</b></p><div class="example-contents"><p><a href="systemd-fstab-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-fstab-generator</span>(8)</span></a>
      用于将 <code class="filename">/etc/fstab</code> 转换为本地 mount 单元。
      该生成器将 argv[1] 用作存放单元文件的目录。
      这样，在明确允许使用用户的原生单元文件覆盖 <code class="filename">/etc/fstab</code> 的同时，
      又能确保 <code class="filename">/etc/fstab</code>
      可以覆盖厂商在 <code class="filename">/usr</code> 中默认提供的 mount 单元。</p><p>当 <code class="filename">/etc/fstab</code> 被修改之后，用户应该明确使用
      <span class="command"><strong>systemctl daemon-reload</strong></span> 命令来重新运行所有生成器，
      以强制让 <span class="command"><strong>systemd</strong></span> 重新加载所有单元文件。
      要想挂载新添加到 <code class="filename">fstab</code> 中的挂载点，可以使用 <span class="command"><strong>systemctl start
      <em class="replaceable"><code>/path/to/mountpoint</code></em></strong></span> 或 <span class="command"><strong>systemctl
      start local-fs.target</strong></span> 命令。</p></div></div><br class="example-break"><div class="example"><a name="id-1.8.3"></a><p class="title"><b>例 2. systemd-system-update-generator</b></p><div class="example-contents"><p><a href="systemd-system-update-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-system-update-generator</span>(8)</span></a>
      用于在计划更新系统的时候，将 <code class="filename">default.target</code> 软连接临时指向
      <code class="filename">system-update.target</code> 目标。
      因为需要覆盖用户对
      <code class="filename">default.target</code> 的配置，所以该单元生成器使用 argv[2] 目录存放单元文件。
      详见
      <a href="systemd.offline-updates.html#"><span class="citerefentry"><span class="refentrytitle">systemd.offline-updates</span>(7)</span></a> 手册。
      </p></div></div><br class="example-break"><div class="example"><a name="id-1.8.4"></a><p class="title"><b>例 3. 调试单元生成器</b></p><div class="example-contents"><pre class="programlisting">dir=$(mktemp -d)
SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/system-generators/systemd-fstab-generator \
        "$dir" "$dir" "$dir"
find $dir</pre></div></div><br class="example-break"></div><div class="refsect1"><a name="id-1.9"></a><h2 id="参见">参见<a class="headerlink" title="Permalink to this headline" href="systemd.generator.html#%E5%8F%82%E8%A7%81">¶</a></h2><p>
      <a href="systemd.html#"><span class="citerefentry"><span class="refentrytitle">systemd</span>(1)</span></a>,
      <a href="systemd-cryptsetup-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-cryptsetup-generator</span>(8)</span></a>,
      <a href="systemd-debug-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-debug-generator</span>(8)</span></a>,
      <a href="systemd-fstab-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-fstab-generator</span>(8)</span></a>,
      <a href="http://man7.org/linux/man-pages/man5/fstab.5.html"><span class="citerefentry"><span class="refentrytitle">fstab</span>(5)</span></a>,
      <a href="systemd-getty-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-getty-generator</span>(8)</span></a>,
      <a href="systemd-gpt-auto-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-gpt-auto-generator</span>(8)</span></a>,
      <a href="systemd-hibernate-resume-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-hibernate-resume-generator</span>(8)</span></a>,
      <a href="systemd-rc-local-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-rc-local-generator</span>(8)</span></a>,
      <a href="systemd-system-update-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-system-update-generator</span>(8)</span></a>,
      <a href="systemd-sysv-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd-sysv-generator</span>(8)</span></a>,
      <a href="systemd.unit.html#"><span class="citerefentry"><span class="refentrytitle">systemd.unit</span>(5)</span></a>,
      <a href="systemctl.html#"><span class="citerefentry"><span class="refentrytitle">systemctl</span>(1)</span></a>,
      <a href="systemd.environment-generator.html#"><span class="citerefentry"><span class="refentrytitle">systemd.environment-generator</span>(7)</span></a>
    </p></div></div></body></html>
